#include "Camera.h"

namespace devii
{

Camera::Camera(){
	
	up			= float3( 0.0f, 1.0f, 0.0f );
	right			= float3( 1.0f, 0.0f, 0.0f );
	look			= float3( 0.0f, 0.0f, 1.0f );

	firstUp		= float3( 0.0f, 1.0f, 0.0f );
	firstRight	= float3( 1.0f, 0.0f, 0.0f );
	firstLook		= float3( 0.0f, 0.0f, 1.0f );

	pitch = 0.0f;
	head = 0.0f;
	roll = 0.0f;
	
	position = float3( 0.0f, 0.0f,  0.0f);

	D3DXMatrixIdentity( &view );
	D3DXMatrixIdentity( &rotationMatrix );
	D3DXMatrixIdentity( &world );
	setAngles(0.0f, 0.0f, 0.0f );
	dislocation = float3(0.0f, 0.0f, -100.0f);
}

Camera::~Camera(){
}

void Camera::rotateCamera( float pAngle, float hAngle, float rAngle ){
	//Add angles.
	pitch += pAngle;
	head	+= hAngle;
	roll	+= rAngle;
	
	//Pi * 2
	float revolution = 2 * (float)D3DX_PI;

	
	//Keep angles between 0 and 2PI.
	if( pitch > revolution )
		pitch -= revolution;
	else if( pitch < 0 )
		pitch += revolution;

	if( head > revolution )
		head -= revolution;
	else if( head < 0 )
		head += revolution;

	if( roll > revolution )
		roll -= revolution;
	else if( roll < 0 )
		roll += revolution;

	D3DXMatrixRotationYawPitchRoll( &rotationMatrix, head, pitch, roll);
	
	D3DXVec3TransformCoord( &look, &firstLook, &rotationMatrix );
	D3DXVec3TransformCoord( &up, &firstUp, &rotationMatrix );
	D3DXVec3TransformCoord( &right, &firstRight, &rotationMatrix );
	D3DXMatrixIdentity( &rotationMatrix );
	

}

void Camera::move( float d ){
	position += d * look;
}

void Camera::strafe( float d ){
	position += d * right;
}
//This is how they calculate in DirectX-mathilibs.
void Camera::update(){

	float3 xAxis, yAxis, zAxis, dis;
	//Create negative z-axis.
	//move(-50);
	position += 10*up;
	D3DXVec3Normalize( &zAxis, &( look ) );

	//Create x-axis from cross-product between m_up & z-axis, after cross-product, normalize it.
	D3DXVec3Cross( &xAxis, &up, &zAxis );
	D3DXVec3Normalize( &xAxis, &xAxis );
	
	//Create y-axis from cross-product between z-axis & x-axis.
	D3DXVec3Cross( &yAxis, &zAxis, &xAxis );

	//Create view-matrix, as it appears in D3DX-libs.
	view = D3DXMATRIX( xAxis.x, yAxis.x, zAxis.x, 0, 
						 xAxis.y, yAxis.y, zAxis.y, 0,
						 xAxis.z, yAxis.z, zAxis.z, 0,
						 -D3DXVec3Dot( &xAxis, &position ), -D3DXVec3Dot( &yAxis, &position ), -D3DXVec3Dot( &zAxis, &position ), 1.0f 
						);
	//move(50);
	position -= 10*up;
}

float3 Camera::getPosition(){
	return position;
}

D3DXMATRIX Camera::getView(){
	return view;
}

D3DXMATRIX Camera::getViewProjection(){
	D3DXMATRIX viewProj = view * projection;
	return viewProj;
}

matrix Camera::getFrustum(){
	return projection;
}

float Camera::getHead(){
	return head;
}

float Camera::getPitch(){
	return pitch;
}

float Camera::getRoll(){
	return roll;
}

matrix Camera::getWorld() const
{
	return world;
}

void Camera::setHeight( float y ){
	position.y = y;
}

void Camera::setPosition( float3 pos ){
	position = pos;
}

void Camera::setAngles(float head, float pitch, float roll){
	this->head = head;
	this->pitch = pitch;
	this->roll = roll;


	//Pi * 2
	float revolution = 2 * (float)D3DX_PI;


	//Keep angles between 0 and 2PI.
	if( pitch > revolution )
		pitch -= revolution;
	else if( pitch < 0 )
		pitch += revolution;

	if( head > revolution )
		head -= revolution;
	else if( head < 0 )
		head += revolution;

	if( roll > revolution )
		roll -= revolution;
	else if( roll < 0 )
		roll += revolution;

	D3DXMatrixRotationYawPitchRoll( &rotationMatrix, head, pitch, roll);
	

	D3DXVec3TransformCoord( &look, &firstLook, &rotationMatrix );
	D3DXVec3TransformCoord( &up, &firstUp, &rotationMatrix );
	D3DXVec3TransformCoord( &right, &firstRight, &rotationMatrix );
	D3DXVec3TransformCoord( &dislocation, &dislocation, &rotationMatrix );
	
	//D3DXMatrixIdentity( &rotationMatrix );
}

void Camera::setWorld( const matrix & world )
{
	this->world = world;
}

}